import 'dart:async';

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

/*
 * BLoC:一个由流构成的完全异步的世界，是Google开发的业务逻辑框架，即把业务逻辑单独拿出来放到单独的类中该类成为BloC
 * 1. StreamBuilder包裹有状态的组件，并监听来自BLoC的流，有状态组件的数据来自于这个流
 * 2.调用BLoC的功能处理用户交互事件
 * 3.BLoC处理完毕后将新的数据add到流的sink中
 * 4.StreamBuilder监听到新的数据，产生新的snapshot，并重新调用build，重新构建Widget
 *
 * StreamBuilder和BLoC完美的分离了业务与视图
 */
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'BloC',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        splashColor: Colors.transparent,
      ),
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CounterProvider(
      bloc: CounterBloc(),
      child: Scaffold(
        appBar: AppBar(
          title: Text('BloC'),
        ),
        floatingActionButton: CounterActionButton(),
        body: CounterBody(),
      ),
    );
  }
}

class CounterBody extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    CounterBloc bloc = CounterProvider.of(context).bloc;
    return Center(
      child: StreamBuilder(
        initialData: 0,
        stream: bloc.count,
        builder: (ctx, snapshot) {
          return ActionChip(
              label: Text("${snapshot.data}"),
              onPressed: () {
                bloc.counterSink.add(1);
              });
        },
      ),
    );
  }
}

// 定义悬浮按钮
class CounterActionButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    CounterBloc bloc = CounterProvider.of(context).bloc;
    return FloatingActionButton(
      // 添加数据
      onPressed: () => bloc.counterSink.add(1),
      child: Icon(Icons.add),
    );
  }
}

// 定义InheritedWidget 组件间共享数据
class CounterProvider extends InheritedWidget {
  final Widget child;
  final CounterBloc bloc;

  CounterProvider({this.child, this.bloc}) : super(child: child);

  static CounterProvider of(BuildContext context) =>
      context.dependOnInheritedWidgetOfExactType();

  @override
  bool updateShouldNotify(CounterProvider oldWidget) {
    return true;
  }
}

// 定义BloC
class CounterBloc {
  int _count = 0;

  // 用户发送数据的Controller
  final _countActionController = StreamController<int>();

  StreamSink<int> get counterSink => _countActionController.sink;

  // 接收数据并绑定到实体
  final _counterController = StreamController<int>();

  Stream<int> get count => _counterController.stream;

  CounterBloc() {
    // 数据改变回调到counterController并映射到UI
    _countActionController.stream.listen(onData);
  }

  // 接收到数据处理
  void onData(int data) {
    _count += data;
    // 数据发生改变自动改变视图
    _counterController.add(_count);
  }

  // 释放资源
  void dispose() {
    _countActionController.close();
    _counterController.close();
  }
}
